
package xj.graph2d.app.diagram;

import java.util.HashMap;
import java.util.Map;

import xj.graph2d.Document;
import xj.graph2d.DrawShape;
import xj.graph2d.DrawShapeBase;
import xj.graph2d.DrawShapeConstants;
import xj.graph2d.DrawShapeFactory;
import xj.graph2d.GraphEdgeBase;
import xj.graph2d.GraphNodeBase;
import xj.graph2d.app.DrawApp;
import xj.graph2d.layout.PackageDiagramLayout;
import xj.graph2d.shapes.uml.UMLUtil;
import xj.graph2d.shapes.uml.PackageShape;
import xj.graph2d.template.UMLTemplate;


public class PackageDiagramBuilder extends DiagramBuilder { 

  public PackageDiagramBuilder(DrawApp main, String name) {
    super(main, name, Document.DocumentType.UML_Package_Diagram);

    diagram.setGraphLayoutManager(new PackageDiagramLayout(diagram));    
  }

  public static GraphNodeBase makePackageShape(String name, 
					       boolean atomic) { 
    if (name != null) { 
      String tempName = (atomic ? "UMLPackageDiagram.Package1" : "UMLPackageDiagram.Package2");
      DrawShapeFactory factory = DrawShapeFactory.getInstance();
      DrawShapeBase proto = factory.getPrototype(tempName);
      DrawShape newShape = DrawShapeFactory.cloneDrawShape(proto, null, 
							   DrawShapeConstants.CLONE_PROTOTYPE_DRAW_ATTR);

      PackageShape pkg  = (PackageShape) newShape;
      if (!atomic) { 
	pkg.setSize(100, 60);
	pkg.setLayoutSubnodes(true);
      }
      int role = (atomic ? DrawShapeConstants.ROLE_NODE_LABEL
		  : DrawShapeConstants.ROLE_NODE_TITLE_LABEL);
      UMLUtil.setName(pkg, role, name);
      return pkg;
    }
    return null;
  }

  public static GraphEdgeBase makeDependencyEdge() { 
    DrawShapeFactory factory = DrawShapeFactory.getInstance();
    DrawShapeBase proto = factory.getPrototype("UMLPackageDiagram.Dependency1");
    DrawShape newShape = 
      DrawShapeFactory.cloneDrawShape(proto, null,
				      DrawShapeConstants.CLONE_PROTOTYPE_DRAW_ATTR);
    GraphEdgeBase edge = (GraphEdgeBase) newShape; 
    edge.setEdgeType(UMLTemplate.DEPENDENCY_EDGE);
    edge.setHeadOffset(0, 0);
    edge.setTailOffset(0, 0);
    return edge;
  }

  public GraphNodeBase addPackage(String name, boolean atomic) { 
    return addPackage(name, name, atomic);
  }

  public GraphNodeBase addPackage(String name, String fullname, boolean atomic) { 
    if (diagram != null &&
	name != null) {       
      GraphNodeBase pkg  = makePackageShape(name, atomic); 
      diagram.addNode(pkg);
      if (fullname == null) { 
	fullname = name; 
      }
      pkgMap.put(fullname, pkg);
      return pkg; 
    }
    return null;
  }

  public void addSubpackage(String parent, 
			    String name, boolean atomic) { 
    addSubpackage(parent, name, null, atomic);
  }

  public void addSubpackage(String parent, 
			    String name, String fullname, boolean atomic) { 
    if (diagram != null &&
	name != null &&
	parent != null) { 
      GraphNodeBase sub = makePackageShape(name, atomic); 
      if (fullname == null) { 
	fullname = parent + "." + name; 
      }
      pkgMap.put(fullname, sub);

      GraphNodeBase p = pkgMap.get(parent);
      if (p != null) { 
	p.addShape(sub);
      } else {
	diagram.addNode(sub);
      }
    }
  }

  public void addDependency(String pkg1, 
			    String pkg2) { 
    if (pkg1 != null && 
	pkg2 != null) { 
      GraphNodeBase p1 = pkgMap.get(pkg1); 
      GraphNodeBase p2 = pkgMap.get(pkg2); 
      if (p1 != null && 
	  p2 != null) { 
	GraphEdgeBase edge = makeDependencyEdge(); 	
	diagram.addEdge(edge);
	diagram.connectSource(edge, p1);
	diagram.connectDestination(edge, p2);	    
	edge.setHeadOffset(0, 0);
	edge.setTailOffset(0, 0);
      }
    }
  }

  public void clearDiagram(){
    pkgMap.clear();
    diagram.removeAllNodes();
    diagram.removeAll();
  }

  protected Map<String, GraphNodeBase> pkgMap = new HashMap<String, GraphNodeBase>();

}